/*
 * TF卡容量检测程序
 * 使用标准Linux接口读取TF卡的总容量和剩余容量
 * 
 * 编译方法: make
 * 使用方法: ./tf_test [挂载路径]
 * 示例: ./tf_test /mnt/tf_card
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>

// 如果系统没有定义PATH_MAX，使用默认值
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif

/**
 * 格式化字节数为可读格式
 * @param bytes 字节数
 * @param buffer 输出缓冲区
 * @param buffer_size 缓冲区大小
 */
void format_bytes(unsigned long long bytes, char *buffer, size_t buffer_size) {
    const char *units[] = {"B", "KB", "MB", "GB", "TB"};
    int unit_index = 0;
    double size = (double)bytes;
    
    while (size >= 1024.0 && unit_index < 4) {
        size /= 1024.0;
        unit_index++;
    }
    
    if (unit_index == 0) {
        snprintf(buffer, buffer_size, "%llu %s", bytes, units[unit_index]);
    } else {
        snprintf(buffer, buffer_size, "%.2f %s", size, units[unit_index]);
    }
}

/**
 * 检查路径是否为挂载点
 * @param path 路径
 * @return 1: 是挂载点, 0: 不是挂载点, -1: 错误
 */
int is_mount_point(const char *path) {
    struct stat path_stat, parent_stat;
    char parent_path[PATH_MAX];
    
    if (stat(path, &path_stat) != 0) {
        return -1;
    }
    
    // 构造父目录路径
    snprintf(parent_path, sizeof(parent_path), "%s/..", path);
    
    if (stat(parent_path, &parent_stat) != 0) {
        return -1;
    }
    
    // 如果设备号不同，说明是挂载点
    return (path_stat.st_dev != parent_stat.st_dev);
}

/**
 * 获取文件系统容量信息
 * @param mount_path 挂载路径
 * @return 0: 成功, -1: 失败
 */
int get_tf_capacity_info(const char *mount_path) {
    struct statvfs vfs;
    unsigned long long total_bytes, free_bytes, used_bytes;
    double usage_percent;
    char total_str[64], free_str[64], used_str[64];
    
    // 检查路径是否存在
    if (access(mount_path, F_OK) != 0) {
        fprintf(stderr, "错误: 路径 '%s' 不存在\n", mount_path);
        return -1;
    }
    
    // 获取文件系统统计信息
    if (statvfs(mount_path, &vfs) != 0) {
        fprintf(stderr, "错误: 无法获取 '%s' 的文件系统信息: %s\n", 
                mount_path, strerror(errno));
        return -1;
    }
    
    // 计算容量信息
    total_bytes = (unsigned long long)vfs.f_blocks * vfs.f_frsize;
    free_bytes = (unsigned long long)vfs.f_bavail * vfs.f_frsize;
    used_bytes = total_bytes - free_bytes;
    
    // 计算使用率
    if (total_bytes > 0) {
        usage_percent = (double)used_bytes / total_bytes * 100.0;
    } else {
        usage_percent = 0.0;
    }
    
    // 格式化输出
    format_bytes(total_bytes, total_str, sizeof(total_str));
    format_bytes(free_bytes, free_str, sizeof(free_str));
    format_bytes(used_bytes, used_str, sizeof(used_str));
    
    // 打印结果
    printf("=================== TF卡容量信息 ===================\n");
    printf("挂载路径: %s\n", mount_path);
    
    // 检查是否为挂载点
    int mount_check = is_mount_point(mount_path);
    if (mount_check == 1) {
        printf("状态: 已挂载\n");
    } else if (mount_check == 0) {
        printf("状态: 非挂载点 (可能是普通目录)\n");
    } else {
        printf("状态: 无法确定\n");
    }
    
    printf("文件系统类型: %s\n", "未知");  // statvfs不提供文件系统类型信息
    printf("块大小: %lu 字节\n", vfs.f_frsize);
    printf("总块数: %lu\n", vfs.f_blocks);
    printf("可用块数: %lu\n", vfs.f_bavail);
    printf("================================================\n");
    printf("总容量: %s\n", total_str);
    printf("已使用: %s (%.1f%%)\n", used_str, usage_percent);
    printf("剩余容量: %s (%.1f%%)\n", free_str, 100.0 - usage_percent);
    printf("================================================\n");
    
    return 0;
}

/**
 * 打印使用帮助
 */
void print_usage(const char *program_name) {
    printf("TF卡容量检测工具\n");
    printf("用法: %s [挂载路径]\n", program_name);
    printf("\n");
    printf("参数说明:\n");
    printf("  挂载路径    TF卡的挂载路径 (默认: /mnt)\n");
    printf("\n");
    printf("示例:\n");
    printf("  %s /mnt/tf_card     # 检测 /mnt/tf_card 的容量\n", program_name);
    printf("  %s /media/sd        # 检测 /media/sd 的容量\n", program_name);
    printf("  %s                  # 检测 /mnt 的容量\n", program_name);
    printf("\n");
    printf("常见TF卡挂载路径:\n");
    printf("  /mnt/tf_card\n");
    printf("  /mnt/sd\n");
    printf("  /media/mmcblk1p1\n");
    printf("  /run/media/user/XXX\n");
}

int main(int argc, char *argv[]) {
    const char *mount_path = "/mnt";  // 默认挂载路径
    
    // 解析命令行参数
    if (argc > 1) {
        if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
            print_usage(argv[0]);
            return 0;
        }
        mount_path = argv[1];
    }
    
    printf("TF卡容量检测程序 v1.0\n");
    printf("目标路径: %s\n\n", mount_path);
    
    // 获取并显示容量信息
    if (get_tf_capacity_info(mount_path) != 0) {
        printf("\n提示: 请确保TF卡已正确挂载到指定路径\n");
        printf("可以使用以下命令查看挂载情况:\n");
        printf("  mount | grep mmc\n");
        printf("  df -h\n");
        printf("  lsblk\n");
        return 1;
    }
    
    return 0;
}